#include "LinuxNetworkManager.h"
#include "NetworkEventCallback.h"
#include <iostream>
#include <fstream>
#include <nlohmann/json.hpp> // Include the nlohmann::json header
#include <net/if.h>          // Include for struct ifreq
#include <sys/ioctl.h>       // Include for ioctl function
#include <linux/if_arp.h>    // Include for ARPHRD_ETHER definition
#include <unistd.h>          // Include for close function
using json = nlohmann::json; // Define alias for convenience

LinuxNetworkManager::LinuxNetworkManager(UeventListener* listener)
    : m_listener(listener)
{
}

LinuxNetworkManager::~LinuxNetworkManager()
{
    // 若需要释放资源，可在此处执行
    // 通常不需要显式delete listener, 由外部管理 listener 的生命周期
}

bool LinuxNetworkManager::nremoveRoute(const std::string &destination,
    const std::string &gateway,
    const std::string &ifName)
{
    // 拼装命令
    std::ostringstream oss;
    oss << "ip route del " << destination;

    // 如果有指定 gateway
    if (!gateway.empty()) {
    oss << " via " << gateway;
    }
    // 如果有指定接口
    if (!ifName.empty()) {
    oss << " dev " << ifName;
    }

    // 执行系统命令
    int ret = std::system(oss.str().c_str());
    if (ret != 0) {
    std::cerr << "[LinuxNetworkManager] Failed to remove route. Command: "
    << oss.str() << " (return code=" << ret << ")\n";
    return false;
    }

    std::cout << "[LinuxNetworkManager] Removed route: " << destination
    << " via " << (gateway.empty() ? "<none>" : gateway)
    << (ifName.empty() ? "" : (" dev " + ifName)) << std::endl;

    return true;
}

bool LinuxNetworkManager::naddRoute(const std::string &destCidr,
    const std::string &gateway,
    const std::string &ifName)
{
    // 组装命令
    std::ostringstream oss;
    oss << "ip route add " << destCidr;  // e.g. "ip route add 192.168.10.0/24"

    // 若指定了网关，则加 " via <gateway>"
    if (!gateway.empty()) {
    oss << " via " << gateway;
    }
    // 若指定了接口，则加 " dev <ifName>"
    if (!ifName.empty()) {
    oss << " dev " << ifName;
    }

    // 例： "ip route add 192.168.10.0/24 via 192.168.10.1 dev eth0"

    // 执行系统命令
    int ret = std::system(oss.str().c_str());
    if (ret != 0) {
    std::cerr << "[LinuxNetworkManager] Failed to add route. Command: "
    << oss.str() << " (return code=" << ret << ")\n";
    return false;
    }

    std::cout << "[LinuxNetworkManager] Added route: " << destCidr
    << (gateway.empty() ? "" : (" via " + gateway))
    << (ifName.empty() ? "" : (" dev " + ifName)) << std::endl;
    return true;
}

static int netmaskToPrefix(const std::string &netmask)
{
    struct in_addr in;
    // 尝试解析字符串形式的子网掩码
    if (inet_pton(AF_INET, netmask.c_str(), &in) != 1) {
        // 解析失败
        return -1;
    }

    uint32_t mask = ntohl(in.s_addr); // 转换为主机字节序
    int prefixLen = 0;
    // 统计 mask 连续的高位 1 的个数
    while (mask & 0x80000000) {
        prefixLen++;
        mask <<= 1;
    }
    return prefixLen;
}


// 将 MAC 地址字符串（"00:11:22:33:44:55"）解析为 6 字节
static bool parseMacString(const std::string &macStr, unsigned char mac[6])
{
    unsigned int values[6];
    if (std::sscanf(macStr.c_str(), "%x:%x:%x:%x:%x:%x",
                    &values[0], &values[1], &values[2],
                    &values[3], &values[4], &values[5]) != 6) {
        return false;
    }
    for (int i = 0; i < 6; i++) {
        mac[i] = static_cast<unsigned char>(values[i]);
    }
    return true;
}

bool LinuxNetworkManager::nsetMacAddress(const std::string &ifName, const std::string &macAddr)
{
    // 1) 解析传入的 MAC 字符串为 6 字节
    unsigned char mac[6];
    if (!parseMacString(macAddr, mac)) {
        std::cerr << "[LinuxNetworkManager] 无效MAC地址格式: "
                  << macAddr << std::endl;
        return false;
    }

    // 2) 先将接口置为 DOWN（若驱动要求，否则可能报错）
    nsetInterfaceStatus(ifName, false);

    // 3) 使用 ioctl(SIOCSIFHWADDR) 设置 MAC
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        std::cerr << "[LinuxNetworkManager] Failed to create socket for nsetMacAddressIoctl\n";
        return false;
    }

    struct ifreq ifr;
    std::memset(&ifr, 0, sizeof(ifr));

    // 拷贝接口名
    std::strncpy(ifr.ifr_name, ifName.c_str(), IFNAMSIZ - 1);

    // 填写 MAC 地址信息
    ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;

    // 拷贝 MAC 6 字节到 sa_data
    std::memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);

    // 调用 ioctl
    if (ioctl(sockfd, SIOCSIFHWADDR, &ifr) < 0) {
        std::cerr << "[LinuxNetworkManager] ioctl(SIOCSIFHWADDR) failed for "
                  << ifName << "\n";
        close(sockfd);
        return false;
    }

    close(sockfd);

    // 4) 将接口重新置为 UP（若需要继续使用）
    nsetInterfaceStatus(ifName, true);

    std::cout << "[LinuxNetworkManager] Successfully set MAC address: "
              << macAddr << " for interface: " << ifName << std::endl;
    return true;
}

bool nsetIPAddr(const std::string &ifname, const std::string &ip_addr, const std::string &netmask)
{
    // 1. 创建 Socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        std::perror("socket");
        return false;
    }

    // 2. 设置 IP 地址 (SIOCSIFADDR)
    {
        struct ifreq ifr;
        std::memset(&ifr, 0, sizeof(ifr));
        std::strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);

        struct sockaddr_in sin;
        std::memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;

        // 将字符串形式的 IP 转为二进制
        if (inet_pton(AF_INET, ip_addr.c_str(), &sin.sin_addr) <= 0) {
            std::cerr << "无效的 IP 地址: " << ip_addr << std::endl;
            close(sockfd);
            return false;
        }
        std::memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr_in));

        if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
            std::perror("ioctl(SIOCSIFADDR)");
            close(sockfd);
            return false;
        }
    }

    // 3. 设置子网掩码 (SIOCSIFNETMASK)
    {
        struct ifreq ifr;
        std::memset(&ifr, 0, sizeof(ifr));
        std::strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);

        struct sockaddr_in sin;
        std::memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;

        // 将字符串形式的子网掩码转为二进制
        if (inet_pton(AF_INET, netmask.c_str(), &sin.sin_addr) <= 0) {
            std::cerr << "无效的子网掩码: " << netmask << std::endl;
            close(sockfd);
            return false;
        }
        std::memcpy(&ifr.ifr_netmask, &sin, sizeof(struct sockaddr_in));

        if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
            std::perror("ioctl(SIOCSIFNETMASK)");
            close(sockfd);
            return false;
        }
    }

    // 4. 将网口置为 UP (SIOCSIFFLAGS)
    {
        struct ifreq ifr;
        std::memset(&ifr, 0, sizeof(ifr));
        std::strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);

        if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
            std::perror("ioctl(SIOCGIFFLAGS)");
            close(sockfd);
            return false;
        }
        // 设置 IFF_UP 标志
        ifr.ifr_flags |= IFF_UP;

        if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
            std::perror("ioctl(SIOCSIFFLAGS)");
            close(sockfd);
            return false;
        }
    }

    close(sockfd);
    return true;
}

void LinuxNetworkManager::initialize()
{
    // 如果想在此处启动 UeventListener, 可以这样:
    if (m_listener) {
        m_listener->startListening();
    }
    // 如果有其他初始化逻辑, 例如
    //  - 加载配置文件
    //  - 扫描当前接口并同步到 m_configMap
    // 可在此进行
    std::cout << "[LinuxNetworkManager] Initialized.\n";
}

//获取指定网络接口的 MAC 地址
std::string LinuxNetworkManager::ngetMacAddress(const std::string &ifName){
     // 创建套接字
     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
     if (sockfd < 0) {
         std::cerr << "[LinuxNetworkManager] Failed to create socket for ngetMacAddress\n";
         return std::string(); // 返回空字符串或可改为抛异常
     }
 
     // 准备 ifreq 结构
     struct ifreq ifr;
     std::memset(&ifr, 0, sizeof(ifr));
     // 将接口名复制到 ifr_name
     std::strncpy(ifr.ifr_name, ifName.c_str(), IFNAMSIZ - 1);
 
     // 使用 ioctl 调用获取 MAC 地址
     if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
         std::cerr << "[LinuxNetworkManager] ioctl SIOCGIFHWADDR failed for: " 
                   << ifName << "\n";
         close(sockfd);
         return std::string();
     }
 
     close(sockfd);
 
     // MAC 地址保存在 ifr.ifr_hwaddr.sa_data 中
     unsigned char mac[6];
     std::memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
 
     // 转换为字符串格式：xx:xx:xx:xx:xx:xx
     char macStr[18]; // 17 chars + null terminator
     std::snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
                   mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 
     return std::string(macStr);
}

//获取指定网络接口的 IPv4 地址
std::string LinuxNetworkManager::ngetIPAddr(const std::string &ifName){
    // 创建套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        std::cerr << "[LinuxNetworkManager] ngetIPAddr方法创建socket失败\n";
        return std::string(); 
    }

    // 准备 ifreq 结构
    struct ifreq ifr;
    std::memset(&ifr, 0, sizeof(ifr));
    // 将接口名复制到 ifr_name
    std::strncpy(ifr.ifr_name, ifName.c_str(), IFNAMSIZ - 1);

    // 使用 ioctl 调用获取 IPv4 地址
    if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
        std::cerr << "[LinuxNetworkManager] ioctl SIOCGIFADDR failed for: " 
                  << ifName << "\n";
        close(sockfd);
        return std::string();
    }

    close(sockfd);

    // IPv4 地址保存在 ifr.ifr_addr 中
    struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(&ifr.ifr_addr);
    
    // 转换为字符串格式
    char ipStr[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &addr->sin_addr, ipStr, sizeof(ipStr));

    return std::string(ipStr);
}

//设置网络接口的状态
bool LinuxNetworkManager::nsetInterfaceStatus(const std::string &ifName, bool enable)
{
    // 1) 创建套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        std::cerr << "[LinuxNetworkManager] nsetInterfaceStatus: 创建socket失败\n";
        return false;
    }

    // 2) 获取当前接口标志位
    struct ifreq ifr;
    std::memset(&ifr, 0, sizeof(ifr));
    std::strncpy(ifr.ifr_name, ifName.c_str(), IFNAMSIZ - 1);

    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
        std::cerr << "[LinuxNetworkManager] nsetInterfaceStatus: SIOCGIFFLAGS failed for "
                  << ifName << "\n";
        close(sockfd);
        return false;
    }

    // 3) 根据参数 enable 设置或清除 IFF_UP 标志
    if (enable) {
        ifr.ifr_flags |= IFF_UP;    // 添加UP标志
    } else {
        ifr.ifr_flags &= ~IFF_UP;   // 清除UP标志
    }

    // 4) 写回新的接口标志位
    if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
        std::cerr << "[LinuxNetworkManager] nsetInterfaceStatus: SIOCSIFFLAGS failed for "
                  << ifName << "\n";
        close(sockfd);
        return false;
    }

    close(sockfd);

    std::cout << "[LinuxNetworkManager] Interface " << ifName 
              << (enable ? " set UP" : " set DOWN") << " successfully.\n";
    return true;
}

void LinuxNetworkManager::registerCallback(NetworkEventCallback* callback)
{
    if (m_listener) {
        m_listener->addCallback(callback);
    }
}

void LinuxNetworkManager::unregisterCallback(NetworkEventCallback* callback)
{
    if (m_listener) {
        m_listener->removeCallback(callback);
    }
}

void LinuxNetworkManager::loadConfigsFromFile(const std::string& filePath)
{
    std::cout << "[LinuxNetworkManager] loadConfigsFromFile(" 
    << filePath << ")" << std::endl;

    // 1. 打开文件
    std::ifstream ifs(filePath);
    if (!ifs.is_open()) {
        std::cerr << "[LinuxNetworkManager] Failed to open config file: " 
                << filePath << std::endl;
        return;
    }

    // 2. 解析 JSON
    json jRoot;
    try {
        ifs >> jRoot;  // 直接将流读入到 nlohmann::json 对象
    } catch (const std::exception& ex) {
        std::cerr << "[LinuxNetworkManager] JSON解析错误: " 
                << ex.what() << std::endl;
        return;
    }

    // 3. 检查 "interfaces" 数组
    if (!jRoot.contains("interfaces") || !jRoot["interfaces"].is_array()) {
        std::cerr << "[LinuxNetworkManager] Invalid JSON format: no 'interfaces' array.\n";
        return;
    }

    auto jInterfaces = jRoot["interfaces"];

    // 4. 遍历每个接口配置
    for (auto& jIf : jInterfaces) {
        InterfaceConfig cfg;

        // 4.1 获取 name
        if (jIf.contains("name") && jIf["name"].is_string()) {
            cfg.ifName = jIf["name"].get<std::string>();
        } else {
            std::cerr << "[LinuxNetworkManager] interface missing 'name', skip.\n";
            continue;
        }

    // 4.2 获取 mac_address 
        if (jIf.contains("mac_address") && jIf["mac_address"].is_string()) {
            cfg.macAddress = jIf["mac_address"].get<std::string>();
        } else {
            std::cerr << "[LinuxNetworkManager] interface missing 'mac_address', skip.\n";
            continue;
        }

    // 4.3 获取 IPv4
        if (jIf.contains("ipv4") && jIf["ipv4"].is_object()) {
            auto jIPv4 = jIf["ipv4"];
            if (jIPv4.contains("address") && jIPv4["address"].is_string()) {
                cfg.ipv4Address = jIPv4["address"].get<std::string>();
            }
            if (jIPv4.contains("mask") && jIPv4["mask"].is_string()) {
                cfg.ipv4Mask = jIPv4["mask"].get<std::string>();
            }
            if (jIPv4.contains("gateway") && jIPv4["gateway"].is_string()) {
                cfg.gateway = jIPv4["gateway"].get<std::string>(); 
            }
        }

        m_configMap.insert({cfg.ifName, cfg}); 
    }
    std::cout << "[LinuxNetworkManager] 读取默认配置已完成\n";
}
